class Course:
  def __init__(self, c_name, c_no, c_contain):
    self.__c_name = c_name
    self.__c_no = c_no
    self.c_contain = c_contain
    self.c_member = 0

  def get_c_name(self):
    return self.__c_name

  def get_c_no(self):
    return self.__c_no

  def display(self):
    print(f"课程名：{self.__c_name}，课程编号：{self.__c_no}，课程容量：{self.c_contain}人，已选人数：{self.c_member}")

  @staticmethod
  def course_legal(course):
    c_no_list = list(course.get_c_no())
    if len(c_no_list) == 5:
      if c_no_list[0] == "C":
        for i in c_no_list:
          if i.isdigit():
            continue
          elif i.isalpha():
            continue
          else:
            print(f"您所添加的{course.get_c_name()}课程编号{course.get_c_no()}非字母或数字，添加失败！")
            return False
      else:
        print(f"您所添加的{course.get_c_name()}课程编号{course.get_c_no()}前缀错误，添加失败！")
        return False
    else:
      print(f"您所添加的{course.get_c_name()}课程编号{course.get_c_no()}长度不合法，添加失败！")
      return False
    return True


# 定义学生类
class Student:
  def __init__(self, s_name, s_no):
    self.s_name = s_name
    self.__s_no = s_no
    self.courses_matched = []

  def get_s_no(self):
    return self.__s_no

  def display(self):
    print(f"姓名：{self.s_name}，学号：{self.get_s_no()}")
    print("已选课程：")
    for i in self.courses_matched:
      print(f"课程名：{i.get_c_name()}，课程号：{i.get_c_no()}")

  @staticmethod
  def s_no_legal(student):
    s_no_str = student.get_s_no()
    if len(s_no_str) == 8:
      if s_no_str.isdigit():
        return True
      else:
        print(f"{student.s_name}，学号{student.get_s_no()}非数字！")
        return False
    else:
      print(f"{student.s_name}，学号{student.get_s_no()}长度错误！")
      return False


# 选课类
class CourseManager:
  def __init__(self):
    self.course_list = []
    self.students_list = []

  def add_course(self, course):
    """
    添加课程
    :param course: 传入课程对象
    """
    # 调用静态方法验证课程编号是否合法
    for i in self.course_list:
      if i.get_c_name() == course.get_c_name():
        print(f"{course.get_c_name()}已在课程列表中，请勿重复添加！")
        return
      else:
        continue
    if Course.course_legal(course):
      self.course_list.append(course)
      print(f"{course.get_c_name()}信息添加成功")
    else:
      return



  def remove_course(self, del_c_name):
    """
    删除课程
    :param del_c_name:要删除的课程名
    """
    for i in self.course_list:
      if i.get_c_name() == del_c_name:
        self.course_list.remove(i)
        return
    print("没有这门课！")

  def show_course_list(self):
    for i in self.course_list:
      print(f"课程名：{i.get_c_name()}，课程编号：{i.get_c_no()}，课程容量：{i.c_contain}人，已选人数：{i.c_member}")

  def add_student(self, student):
    """
    添加学生
    :param student: 传入学生对象
    """
    if Student.s_no_legal(student):
      self.students_list.append(student)
      print(f"{student.s_name}信息添加成功")
    else:
      print(f"您所要添加的{student.s_name}，学号{student.get_s_no()}格式错误，信息添加不成功！")

  def remove_student(self, del_s_name):
    """
    删除学生
    :param del_s_name:
    """
    for i in self.students_list:
      if i.s_name == del_s_name:
        self.students_list.remove(i)
        return
    print("没有这个学生！")

  def show_students_list(self):
    for i in self.students_list:
      i.display()

  @staticmethod
  def stu_match_course(student, course):
    """
    学生选课
    :param student: 学生对象
    :param course: 课程对象
    """
    # 如过已经选了这门课
    for c_matched in student.courses_matched:
      if course == c_matched:
        print(f"已选过{course.get_c_name()}这门课，选课失败")
        return
      else:
        # 如果所选的课程容量未满
        if course.c_member < course.c_contain:
          student.courses_matched.append(course)
          course.c_member += 1
          print(f"{student.s_name}同学，选{course.get_c_name()}课成功")
        else:
          print(f"{course.get_c_name()}选课人数已满，选课失败")
          return

  @staticmethod
  def stu_remove_course(student, course):
    """
    学生退课
    :param student: 学生对象
    :param course: 课程对象
    """
    if course in student.courses_matched:
      student.courses_matched.remove(course)
      course.c_member -= 1
      print(f"退{course.get_c_name()}课成功")
    else:
      print(f"您的选课列表中没有{course.get_c_name()}课，退课失败")
      return

# ——————————————————————————————————————————————————————————

if __name__ == '__main__':

  # 创建课程Course对象
  course1 = Course("ds", "C408A", 100)
  course2 = Course("co", "C408B", 100)
  course3 = Course("os", "C408C", 80)
  course4 = Course("cn", "C408D", 50)
  # 写3个课程号格式错误的用例
  course5 = Course("xx", "xw1ws", 10)
  course6 = Course("yy", "C/.zp", 20)
  course7 = Course("zz", "qmsxoqunx", 30)
  # 一个已有的课程
  course8 = Course("cn", "C408D", 50)

  courses = [course1, course2, course3, course4, course5, course6, course7, course8]

  # 创建课程管理对象
  cm = CourseManager()

  # 添加课程
  for c in courses:
    cm.add_course(c)

  print("————————————————————————————————————————————————————————")

  print("添加课程后的课程列表：")
  cm.show_course_list()

  print("————————————————————————————————————————————————————————")

  # 删除课程
  print(f"即将删除{course4.get_c_name()}")
  cm.remove_course(course4.get_c_name())
  print(f"删除课程{course4.get_c_name()}后的课程列表：")
  cm.show_course_list()

  print("————————————————————————————————————————————————————————")

  # 创建学生Student对象
  student1 = Student("李明", "20250001")
  student2 = Student("王军", "20250002")
  student3 = Student("刘志", "20250003")
  student4 = Student("张华", "20250004")
  # 写2个学号格式错误的用例
  student5 = Student("周成", "1sqm2omx")
  student6 = Student("程丽", "21390")

  students = [student1, student2, student3, student4, student5, student6]

  # 添加学生
  for s in students:
    cm.add_student(s)
  print("添加学生后的学生列表：")
  cm.show_students_list()

  print("————————————————————————————————————————————————————————")

  # 学生选课的实现
  print("开始选课")
  cm.stu_match_course(student1, course3)
  cm.stu_match_course(student1, course2)
  cm.stu_match_course(student2, course1)

  print("————————————————————————————————————————————————————————")

  print(f"选课后的{student1.s_name}的系统信息更新为：")
  student1.display()

  print("————————————————————————————————————————————————————————")

  # 学生退课
  print("学生进行退课")
  cm.stu_remove_course(student1, course3)
  print(f"退课后的{student1.s_name}的系统信息更新为：")
  student1.display()

  print("————————————————————————————————————————————————————————")

  # 显示全部课程选课情况
  print("系统全部选课信息：")
  cm.show_course_list()
